package lg.minecraft.plugin.pokemonmenu.gui;

import com.cobblemon.mod.common.api.battles.model.PokemonBattle;
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
import com.cobblemon.mod.common.battles.BattleRegistry;
import com.cobblemon.mod.common.pokemon.Pokemon;
import lg.minecraft.plugin.cobblemoncore.util.BukkitNmsConverter;
import lg.minecraft.plugin.library.inventory.ClickInventoryContext;
import lg.minecraft.plugin.library.inventory.InventoryContext;
import lg.minecraft.plugin.pokemonmenu.LGPokemonMenu;
import lg.minecraft.plugin.pokemonmenu.PokemonPlayer;
import lg.minecraft.plugin.pokemonmenu.display.PokemonDisplayHandler;
import lg.minecraft.plugin.pokemonmenu.event.PlayerEndBattleHealEvent;
import lg.minecraft.plugin.pokemonmenu.manager.DisplayPokemonManger;
import lg.minecraft.plugin.pokemonmenu.manager.PokemonPlayerManger;
import lg.minecraft.plugin.pokemonmenu.util.Position;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;

import java.util.UUID;
import java.util.function.Function;

/**
 * @author langle__
 * @version 1.0
 */
public class PartyInventor extends AbstractPokemonInventory {

    private static final int[] POKEMON_ARRAY = {10, 11, 12, 14, 15, 16};
    private static final int[] GLASS_ARRAY = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 35, 36, 44, 45, 46, 47, 48, 50, 51, 52, 53};

    public PartyInventor(UUID targetUUID) {
        super(targetUUID, LGPokemonMenu.getMessage().getGuiTitleParty());
    }

    @Override
    public void onDrawInventory(Player player) {
        saveAndClearMainHand(player.getInventory());
        PokemonPlayer pokemonPlayer = PokemonPlayerManger.INSTANCE.getPokemonPlayer(targetUUID);

        Function<Pokemon, ItemStack> function = player.hasPermission("LGPokemonMenu.to_item") ? LGPokemonMenu.getGuiItem()::getPartyPokemon : LGPokemonMenu.getGuiItem()::getPartyPokemonNoToItem;
        ItemStack air_pokemon = player.hasPermission("LGPokemonMenu.edit") ? LGPokemonMenu.getGuiItem().getEditAirPoke() : LGPokemonMenu.getGuiItem().getAirPoke();
        for (int i = 0; i < 6; i++) {
            int slot = POKEMON_ARRAY[i];
            Pokemon pokemon = pokemonPlayer.getPartyPokemon(i);
            ItemStack item = pokemon == null ? air_pokemon : function.apply(pokemon);
            inventory.setItem(slot, item);
        }
        if (select != null) {
            int slot = POKEMON_ARRAY[select.getSlot()];
            Pokemon pokemon = pokemonPlayer.getPokemon(select);
            if (pokemon != null) {
                inventory.setItem(slot, LGPokemonMenu.getGuiItem().getSelectPokemon(pokemon));
            }
        }
        if (remove != null) {
            int slot = POKEMON_ARRAY[remove.getSlot()];
            Pokemon pokemon = pokemonPlayer.getPokemon(remove);
            if (pokemon != null) {
                inventory.setItem(slot, LGPokemonMenu.getGuiItem().getRemovePokemon(pokemon));
            }
        }
        for (int slot : GLASS_ARRAY) inventory.setItem(slot, LGPokemonMenu.getGuiItem().getBorder());
        if (player.hasPermission("LGPokemonMenu.gui.open.pc")) {
            inventory.setItem(49, LGPokemonMenu.getGuiItem().getOpenPC());
        } else {
            inventory.setItem(49, LGPokemonMenu.getGuiItem().getBorder());
        }
        if (player.hasPermission("LGPokemonMenu.show.party")) {
            inventory.setItem(34, LGPokemonMenu.getGuiItem().getShowParty());
        } else {
            inventory.setItem(34, LGPokemonMenu.getGuiItem().getNoShowPartyPermission());
        }
        if (player.hasPermission("LGPokemonMenu.open_wild_pokemon")) {
            inventory.setItem(37, LGPokemonMenu.getGuiItem().getOpenWildPokemon(pokemonPlayer.isOpenWildPokemon()));
        } else {
            inventory.setItem(37, LGPokemonMenu.getGuiItem().getNoOpenWildPokemonPermission());
        }
        if (player.hasPermission("LGPokemonMenu.view_player_party")) {
            inventory.setItem(38, LGPokemonMenu.getGuiItem().getViewPlayerPokemon(pokemonPlayer.isViewPlayerParty()));
        } else {
            inventory.setItem(38, LGPokemonMenu.getGuiItem().getNoViewPlayerPokemonPermission());
        }
        if (player.hasPermission("LGPokemonMenu.bypass.money_heal")) {
            inventory.setItem(40, LGPokemonMenu.getGuiItem().getNoMoneyHeal());
        } else if (LGPokemonMenu.getEconomy() == null) {
            inventory.setItem(40, LGPokemonMenu.getGuiItem().getFunctionNoEnable());
        } else if (player.hasPermission("LGPokemonMenu.money_heal")) {
            inventory.setItem(40, LGPokemonMenu.getGuiItem().getMoneyHeal(LGPokemonMenu.getMainConfig().getMoneyHeal()));
        } else {
            inventory.setItem(40, LGPokemonMenu.getGuiItem().getNoMoneyHealPermission());
        }
        if (player.hasPermission("LGPokemonMenu.auto_heal")) {
            inventory.setItem(41, LGPokemonMenu.getGuiItem().getAutoHeal(pokemonPlayer.isAutoHeal()));
        } else {
            inventory.setItem(41, LGPokemonMenu.getGuiItem().getNoAutoHealPermission());
        }
        if (player.hasPermission("LGPokemonMenu.disabled_view")) {
            inventory.setItem(39, LGPokemonMenu.getGuiItem().getDisabledView(pokemonPlayer.isDisabledView()));
        } else {
            inventory.setItem(39, LGPokemonMenu.getGuiItem().getNoDisabledViewPermission());
        }
        if (player.hasPermission("LGPokemonMenu.end_battle")) {
            inventory.setItem(31, LGPokemonMenu.getGuiItem().getEndBattle());
        } else {
            inventory.setItem(31, LGPokemonMenu.getGuiItem().getNoEndBattlePermission());
        }
        if (player.hasPermission("LGPokemonMenu.edit_mode")) {
            inventory.setItem(43, LGPokemonMenu.getGuiItem().getEditMode(pokemonPlayer.isEditMode()));
        } else {
            inventory.setItem(43, LGPokemonMenu.getGuiItem().getNoEditModePermission());
        }

        inventory.setItem(28, LGPokemonMenu.getGuiItem().getNoFUnction());
        inventory.setItem(29, LGPokemonMenu.getGuiItem().getNoFUnction());
        inventory.setItem(30, LGPokemonMenu.getGuiItem().getNoFUnction());
        inventory.setItem(32, LGPokemonMenu.getGuiItem().getNoFUnction());
        inventory.setItem(33, LGPokemonMenu.getGuiItem().getNoFUnction());
        inventory.setItem(42, LGPokemonMenu.getGuiItem().getNoFUnction());
    }

    @Override
    public void onInventoryClick(ClickInventoryContext context) {
        context.setCancelled(true);
        Player player = context.getPlayer();
        int slot = context.getSlot();
        ClickType click = context.getClick();
        PokemonPlayer pokemonPlayer = PokemonPlayerManger.INSTANCE.getPokemonPlayer(targetUUID);

        Position position = slotToPokemonSlot(slot);
        if (position != null) {
            handlePokemonSlotClick(player, click, pokemonPlayer, position);
        } else if (slot == 49 && player.hasPermission("LGPokemonMenu.gui.open.pc")) {
            new PCInventor(targetUUID, 0).openInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 37 && player.hasPermission("LGPokemonMenu.open_wild_pokemon")) {
            pokemonPlayer.setOpenWildPokemon(!pokemonPlayer.isOpenWildPokemon());
            onDrawInventory(player);
        } else if (slot == 34 && player.hasPermission("LGPokemonMenu.show.party")) {
            int remainingCooldown = DisplayPokemonManger.INSTANCE.getRemainingCooldown(player.getUniqueId());
            if (remainingCooldown > 0 && !player.hasPermission("LGPokemonMenu.bypass.show.cooldown")) {
                player.sendMessage(LGPokemonMenu.getMessage().getDisplayCooldown(remainingCooldown / 1000));
                player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F);
                return;
            } else {
                DisplayPokemonManger.INSTANCE.addCooldown(player.getUniqueId());
                player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            }
            Pokemon[] pokemonArray = new Pokemon[6];
            for (int i = 0; i < 6; i++) {
                Pokemon pokemon = pokemonPlayer.getPartyStore().get(i);
                if (pokemon == null) continue;
                pokemonArray[i] = pokemon.clone(true, BukkitNmsConverter.getRegistryAccess());
            }
            PokemonDisplayHandler.showPartyPokemon(pokemonArray, player.getName());
        } else if (slot == 38 && player.hasPermission("LGPokemonMenu.view_player_party")) {
            pokemonPlayer.setViewPlayerParty(!pokemonPlayer.isViewPlayerParty());
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            onDrawInventory(player);
        } else if (slot == 40) {
            PlayerPartyStore party = pokemonPlayer.getPartyStore();
            if (!LGPokemonMenu.canPartyBeHealed(party)) {
                player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1.0F, 1.0F);
            } else if (player.hasPermission("LGPokemonMenu.bypass.money_heal")) {
                party.heal();
                player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            } else if (player.hasPermission("LGPokemonMenu.money_heal")) {
                Economy economy = LGPokemonMenu.getEconomy();
                if (economy != null) {
                    int value = LGPokemonMenu.getMainConfig().getMoneyHeal();
                    if (!economy.has(player, value)) return;
                    economy.withdrawPlayer(player, value);
                    party.heal();
                    player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
                }
            }
        } else if (slot == 41 && player.hasPermission("LGPokemonMenu.auto_heal")) {
            pokemonPlayer.setAutoHeal(!pokemonPlayer.isAutoHeal());
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            onDrawInventory(player);
        } else if (slot == 39 && player.hasPermission("LGPokemonMenu.disabled_view")) {
            pokemonPlayer.setDisabledView(!pokemonPlayer.isDisabledView());
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            onDrawInventory(player);
        } else if (slot == 31 && player.hasPermission("LGPokemonMenu.end_battle")) {
            PokemonBattle battle = BattleRegistry.INSTANCE.getBattleByParticipatingPlayerId(targetUUID);
            if (battle != null) {
                battle.end();
                Player target = Bukkit.getPlayer(targetUUID);
                Bukkit.getPluginManager().callEvent(new PlayerEndBattleHealEvent(target));
                player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            } else {
                player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 0.5F, 1F);
            }
        } else if (slot == 43 && player.hasPermission("LGPokemonMenu.edit")) {
            pokemonPlayer.setEditMode(!pokemonPlayer.isEditMode());
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.5F, 1F);
            onDrawInventory(player);
        }
    }

    @Override
    public void onInventoryClose(InventoryContext context) {
        super.onInventoryClose(context);
        restoreMainHand(context.getPlayer().getInventory());
    }

    @Override
    protected Position getEmptySlot(PokemonPlayer pokemonPlayer, Position position) {
        return null;
    }

    @Override
    protected Position slotToPokemonSlot(int slot) {
        for (int i = 0; i < POKEMON_ARRAY.length; i++) {
            if (POKEMON_ARRAY[i] == slot) {
                return new Position(i);
            }
        }
        return null;
    }

}
